package ar.com.tallerdos.smartdinner.data;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.annotation.SuppressLint;
import ar.com.tallerdos.smartdinner.model.Identity;

public class EntitiesDataManager {

    private static EntitiesDataManager instance;
    private Boolean fueInicializado = false;

    private Map<String, Map<Integer, Identity>> mapa;
    private Map<String, Integer> mapaIds;

    private EntitiesDataManager() {
	mapa = new HashMap<String, Map<Integer, Identity>>();
	mapaIds = new HashMap<String, Integer>();
    }

    public static synchronized EntitiesDataManager getInstance() {
	if (instance == null) {
	    instance = new EntitiesDataManager();
	}
	return instance;
    }

    @SuppressLint("UseSparseArrays")
    public synchronized List<Identity> getAllEntities(Class<? extends Identity> clazz) {
	initMap(clazz);
	List<Identity> resultado = new ArrayList<Identity>();
	resultado.addAll(mapa.get(clazz.getCanonicalName()).values());
	return resultado;
    }

    public synchronized Identity getEntityById(Class<? extends Identity> clazz, Integer id) {
	if (id == null) {
	    return null;
	}

	if (mapa.get(clazz.getCanonicalName()) != null) {
	    return mapa.get(clazz.getCanonicalName()).get(id);
	}
	return null;
    }

    @SuppressLint({ "UseValueOf", "UseSparseArrays" })
    private synchronized void initMap(Class<?> clazz) {
	if (!mapa.containsKey(clazz.getCanonicalName())) {
	    mapa.put(clazz.getCanonicalName(), new HashMap<Integer, Identity>());
	    mapaIds.put(clazz.getCanonicalName(), new Integer(1));
	}
    }

    public synchronized void putEntity(Identity entity) {
	initMap(entity.getClass());

	if (entity.getId() == null) {
	    Integer id = mapaIds.get(entity.getClass().getCanonicalName());
	    entity.setId(id);
	    id += 1;
	    mapaIds.put(entity.getClass().getCanonicalName(), id);
	} else {
	    if (this.getEntityById(entity.getClass(), entity.getId()) != null) {
		throw new ElementoDuplicadoException();
	    }
	}
	mapa.get(entity.getClass().getCanonicalName()).put(entity.getId(), entity);
    }
    
    public synchronized Boolean updateEntity(Identity entity) {
	initMap(entity.getClass());
	if (entity.getId() == null || deleteEntity(entity)) {
	    this.putEntity(entity);
	    return true;
	}
	return false;
    }

    public synchronized <T extends Identity> Boolean deleteEntity(T entity) {
	return deleteEntity(entity.getClass(), entity.getId());
    }

    public synchronized <T extends Identity> Boolean deleteEntity(Class<?> clazz, Integer id) {
	initMap(clazz);
	
	if (id == null) {
	    throw new NullPointerException();
	}
	Map<Integer, Identity> mapa = this.mapa.get(clazz.getCanonicalName());
	if (mapa.containsKey(id)) {
	    mapa.remove(id);
	    return true;
	} else {
	    return false;	    
	}
    }

    public synchronized Boolean getFueInicializado() {
        return fueInicializado;
    }

    public synchronized void setFueInicializado(Boolean fueInicializado) {
        this.fueInicializado = fueInicializado;
    }
    
    public synchronized void deleteAll() {
	instance = new EntitiesDataManager();
    }
}
